/**
 * 
 */
package com.mc.qrcode;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

/**
 * 二维码 
 * @author w.weizhen
 *
 */
public class QREncode {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			QREncode();//复杂方法,分两个方法.
			QREncode1();//简单方法,一个方法
		} catch (WriterException e) {
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	/**
     * 生成二维码
     */
    public static void QREncode() throws WriterException, IOException 
    {
        String content = "个人博客：https://www.cnblogs.com/huanzi-qch/";//二维码内容
        int width = 500; // 图像宽度
        int height = 500; // 图像高度
        String format = "gif";// 图像类型
        Map<EncodeHintType, Object> hints = new HashMap<>();
        //内容编码格式
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        // 指定纠错等级
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        //设置二维码边的空度，非负数
        hints.put(EncodeHintType.MARGIN, 1);
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
        MatrixToImageWriter.writeToPath(bitMatrix, format, new File("G:/workspace/file/QREncode.png").toPath());// 输出原图片
        MatrixToImageConfig matrixToImageConfig = new MatrixToImageConfig(0xFF000001, 0xFFFFFFFF);
        /*
            问题：生成二维码正常,生成带logo的二维码logo变成黑白
            原因：MatrixToImageConfig默认黑白，需要设置BLACK、WHITE
            解决：https://ququjioulai.iteye.com/blog/2254382
         */
        BufferedImage bufferedImage = LogoMatrix(MatrixToImageWriter.toBufferedImage(bitMatrix,matrixToImageConfig), new File("G:/workspace/file/yyy.jpg"));
//        BufferedImage bufferedImage = LogoMatrix(toBufferedImage(bitMatrix), new File("D:\\logo.png"));
        ImageIO.write(bufferedImage, "gif", new File("G:/workspace/zxing/QREncode.png"));//输出带logo图片
        System.out.println("输出成功.");
    }

    /**
     * 二维码添加logo
     * @param matrixImage 源二维码图片
     * @param logoFile logo图片
     * @return 返回带有logo的二维码图片
     * 参考：https://blog.csdn.net/weixin_39494923/article/details/79058799
     */
    public static BufferedImage LogoMatrix(BufferedImage matrixImage, File logoFile) throws IOException{
        /**
         * 读取二维码图片，并构建绘图对象
         */
        Graphics2D graphics = matrixImage.createGraphics();

        int matrixWidth = matrixImage.getWidth();
        int matrixHeigh = matrixImage.getHeight();

        /**
         * 读取Logo图片
         */
        BufferedImage logo = ImageIO.read(logoFile);

        //开始绘制图片
        graphics.drawImage(logo,matrixWidth/5*2,matrixHeigh/5*2, matrixWidth/5, matrixHeigh/5, null);//绘制
        BasicStroke stroke = new BasicStroke(5,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
        graphics.setStroke(stroke);// 设置笔画对象
        //指定弧度的圆角矩形
        RoundRectangle2D.Float round = new RoundRectangle2D.Float(matrixWidth/5*2, matrixHeigh/5*2, matrixWidth/5, matrixHeigh/5,20,20);
        graphics.setColor(Color.white);
        graphics.draw(round);// 绘制圆弧矩形

        //设置logo 有一道灰色边框
        BasicStroke stroke2 = new BasicStroke(1,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
        graphics.setStroke(stroke2);// 设置笔画对象
        RoundRectangle2D.Float round2 = new RoundRectangle2D.Float(matrixWidth/5*2+2, matrixHeigh/5*2+2, matrixWidth/5-4, matrixHeigh/5-4,20,20);
        graphics.setColor(new Color(128,128,128));
        graphics.draw(round2);// 绘制圆弧矩形

        graphics.dispose();
        matrixImage.flush() ;
        return matrixImage ;
    }
    
    
    
    public static void QREncode1() throws WriterException, IOException
    {
    	// 定义二维码的参数
    	int width = 800; // 图片宽度
    	int height = 800; // 图片高度
    	String format = "jpg"; // 图片格式  如果是png类型，logo图变成黑白的，
    	String content = "https://blog.csdn.net/weixin_44467567/article/details/103876746";// 二维码内容

    	// 1.定义HashMap hints
    	Map<EncodeHintType, Object> hints = new HashMap<>();
    	// 2.hints调用put函数设置字符集、间距以及纠错度为M
    	hints.put(EncodeHintType.CHARACTER_SET, "utf-8");//内容编码格式
    	hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);//纠错等级【L，M，Q，H】
    	hints.put(EncodeHintType.MARGIN, 2);//设置二维码边的空度，非负数
    	
    	// 生成二维码
	    MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
	    // 3.最后用MultiformatWriter函数类调用echoed函数并返回一个值 然后写入文件
	    BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
	    // 这里路径后面的img.png不可省略，前面是自己选取生成的图片地址
	    Path file = new File("G:/workspace/file/img.png").toPath();
	    MatrixToImageWriter.writeToPath(bitMatrix, format, file);
	    //*************添加logo*****************
	    //读取二维码图片
	    BufferedImage bufferedImage = ImageIO.read(new File(file.toString()));
	    //获取画笔
	    Graphics2D graphics = bufferedImage.createGraphics();
	    //读取logo图片
	    BufferedImage logo = ImageIO.read(new File("G:/workspace/file/yys.png"));
	    
	    //设置二维码大小，太大了会覆盖二维码，此处为20%
	    int logoWidth = logo.getWidth() > bufferedImage.getWidth()*2 /10 ? (bufferedImage.getWidth()*2 /10) : logo.getWidth();
	    int logoHeight = logo.getHeight() > bufferedImage.getHeight()*2 /10 ? (bufferedImage.getHeight()*2 /10) : logo.getHeight();
	    //设置logo图片放置的位置，中心
	    int x = (bufferedImage.getWidth() - logoWidth) / 2;
	    int y = (bufferedImage.getHeight() - logoHeight) / 2;
	    
	    //开始绘制图片
        graphics.drawImage(logo,x,y, logoWidth, logoHeight, null);//绘制
        BasicStroke stroke = new BasicStroke(5,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
        graphics.setStroke(stroke);// 设置笔画对象
        //指定弧度的圆角矩形
        RoundRectangle2D.Float round = new RoundRectangle2D.Float(x,y, logoWidth, logoHeight,20,20);
        graphics.setColor(Color.white);
        graphics.draw(round);// 绘制圆弧矩形

        //设置logo 有一道灰色边框
        BasicStroke stroke2 = new BasicStroke(1,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
        graphics.setStroke(stroke2);// 设置笔画对象
        RoundRectangle2D.Float round2 = new RoundRectangle2D.Float(x+2, y+2, logoWidth-4, logoHeight-4,20,20);
        graphics.setColor(new Color(128,128,128));
        graphics.draw(round2);// 绘制圆弧矩形
	    
	    graphics.dispose();
	    logo.flush();
	    bufferedImage.flush();
	    ImageIO.write(bufferedImage, format ,new File("G:/workspace/zxing/img.png"));
    }
    
    
}